package org.common.dao.impl;

import org.common.util.JDBCUtil;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yexi
 */
public abstract class BaseDAOImpl {

    public int baseUpdate(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        int rows = 0;
        try {
            connection = JDBCUtil.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            //设置参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            rows = preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(preparedStatement, connection);
        }
        return rows;
    }

    public <T> T baseQuery(Class<T> clazz, String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        T entity = null;
        try {
            connection = JDBCUtil.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            //设置参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            //执行CURD
            resultSet = preparedStatement.executeQuery();
            // 根据字节码获取所有 的属性
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);// 设置属性可以 访问
            }
            while (resultSet.next()) {
                T obj = clazz.newInstance();
                for (Field field : fields) {
                    this.handleData(field, resultSet, obj);
                }
                entity = obj;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(preparedStatement, connection);
        }
        return entity;
    }

    public <T> List<T> baseQueryList(Class<T> clazz, String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<T> list = null;
        try {
            connection = JDBCUtil.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            //设置参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }
            //执行CURD
            resultSet = preparedStatement.executeQuery();
            list = new ArrayList<>();
            // 根据字节码获取所有 的属性
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);// 设置属性可以 访问
            }
            while (resultSet.next()) {
                T obj = clazz.newInstance();
                for (Field field : fields) {
                    this.handleData(field, resultSet, obj);
                }
                list.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(preparedStatement, connection);
        }
        return list;
    }

    private void handleData(Field field, ResultSet resultSet, Object obj) throws SQLException, IllegalAccessException {
        String fieldName = field.getName().replaceAll("([a-z])([A-Z])", "$1" + "_" + "$2").toLowerCase();
        Object data = resultSet.getObject(fieldName);
        //这些判断是为了适配oracle才加的判断，否则其他数据库并不需要
        if (data instanceof BigDecimal) {
            if (field.getType().getSimpleName().equals("Double")) {
                data = ((BigDecimal) data).doubleValue();
            } else if (field.getType().getSimpleName().equals("Integer")) {
                data = ((BigDecimal) data).intValue();
            }
        }
        if (fieldName.contains("date")) {
            data = resultSet.getDate(fieldName);
        }
        field.set(obj, data);
    }
}
